package com.peaker.advertisingpro.utils

import android.util.Log
import com.google.gson.Gson
import com.peaker.advertisingpro.listener.OnDownloadListener
import com.peaker.advertisingpro.listener.RequestListener
import okhttp3.*
import okio.BufferedSink
import okio.Okio
import okio.Sink
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.net.URLEncoder
import java.util.concurrent.TimeUnit


/**
 *  @ 作者 CODE_LYF
 *  @ 时间   2021/4/8.
 *  代码人生
 */
object HttpUtil {


    private var okHttpClient: OkHttpClient? = null

    init {
        okHttpClient = OkHttpClient()
    }


    /**
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称，后面记得拼接后缀，否则手机没法识别文件类型
     * @param listener     下载监听
     */
    fun download(
        url: String?,
        destFileDir: String?,
        destFileName: String?,
        listener: OnDownloadListener
    ) {
        val request: Request = Request.Builder()
            .url(url)
            .build()
//        val client = OkHttpClient()
//        try {
//            val response: Response = client.newCall(request).execute()
//        } catch (e: IOException) {
//            e.printStackTrace()
//        }
        //异步请求
        okHttpClient!!.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call?, e: IOException?) { // 下载失败监听回调
                listener.onDownloadFailed(e)
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call?, response: Response) {
                var `is`: InputStream? = null
                val buf = ByteArray(2048)
                var len = 0
                var fos: FileOutputStream? = null
                //储存下载文件的目录
                val dir = File(destFileDir)
                if (!dir.exists()) {
                    dir.mkdirs()
                }
                val file = File(dir, destFileName)
                try {
                    `is` = response.body()?.byteStream()
                    val total: Long = response.body()!!.contentLength()
                    fos = FileOutputStream(file)
                    var sum: Long = 0
                    while (`is`!!.read(buf).also { len = it } != -1) {
                        fos.write(buf, 0, len)
                        sum += len.toLong()
                        val progress = (sum * 1.0f / total * 100).toInt()
                        //下载中更新进度条
                        listener.onDownloading(progress)
                    }
                    fos.flush()
                    //下载完成
                    listener.onDownloadSuccess(file)
                } catch (e: Exception) {
                    listener.onDownloadFailed(e)
                } finally {
                    try {
                        if (`is` != null) {
                            `is`.close()
                        }
                        if (fos != null) {
                            fos.close()
                        }
                    } catch (e: IOException) {
                        println("${e.message}")
                    }
                }
            }
        })
    }

    /**
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称，后面记得拼接后缀，否则手机没法识别文件类型
     * @param listener     下载监听
     */
    fun downloadFile(
        url: String?,
        destFileDir: String?,
        destFileName: String?,
        listener: OnDownloadListener
    ) {
        val request: Request = Request.Builder()
            .url(url)
            .build()
//        val client = OkHttpClient()
//        try {
//            val response: Response = client.newCall(request).execute()
//        } catch (e: IOException) {
//            e.printStackTrace()
//        }
        //异步请求
        okHttpClient!!.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call?, e: IOException?) { // 下载失败监听回调
                listener.onDownloadFailed(e)
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call?, response: Response) {
                val dir = File(destFileDir)
                if (!dir.exists()) {
                    dir.mkdirs()
                }
                val file = File(dir, destFileName)
                var sink: Sink? = null
                var bufferedSink: BufferedSink? = null
                try {
                    sink = Okio.sink(file)
                    bufferedSink = Okio.buffer(sink)
                    bufferedSink.writeAll(response.body()!!.source())
                    bufferedSink.close()
                    listener.onDownloadSuccess(file)
                } catch (e: java.lang.Exception) {
                    println("下载失败")
                    listener.onDownloadFailed(e)
                } finally {
                    bufferedSink?.close()
                }
            }
        })
    }

    /**
     * 请求方法
     */
    fun request(): OkHttpClient {
        var build = okHttpClient?.newBuilder()
            ?.connectTimeout(10, TimeUnit.SECONDS)//设置超时时间
            ?.readTimeout(10, TimeUnit.SECONDS)//设置读取超时时间
            ?.writeTimeout(10, TimeUnit.SECONDS)//设置写入超时时间
            ?.build()

        return build!!
    }

    private val MEDIA_TYPE_JSON =
        MediaType.parse("application/json; charset=utf-8") //mdiatype 这个需要和服务端保持一致

    /**
     * okHttp post异步请求
     * @param actionUrl 接口地址
     * @param paramsMap 请求参数
     * @param callBack 请求返回数据回调
     * @param <T> 数据泛型
     * @return
    </T> */
    fun requestPostByAsyn(
        actionUrl: String,
        paramsMap: HashMap<String, String>,
        listener: RequestListener
    ): Call? {
        try {
            val tempParams = StringBuilder()
            var pos = 0
            for (key in paramsMap.keys) {
                if (pos > 0) {
                    tempParams.append("&")
                }
                tempParams.append(java.lang.String.format("%s=%s", key, URLEncoder.encode(paramsMap[key], "utf-8")))
                pos++
            }
            val params = tempParams.toString()
            val body = RequestBody.create(MEDIA_TYPE_JSON, params)

            val request = if (params.isNotEmpty()) {
                Request.Builder().url(actionUrl)
                    .addHeader("mac", SmdtManagerUtils.smdtGetEthMacAddress())
                    .post(body).build()
            } else {
                Request.Builder().url(actionUrl)
//                    .addHeader("mac", SmdtManagerUtils.smdtGetEthMacAddress())
                    .get().build()
            }
            val call: Call = request().newCall(request)
            call.enqueue(object : Callback {
                override fun onFailure(call: Call?, e: IOException) {
                    listener.OnRequestErro("${e.message}")

                }

                @Throws(IOException::class)
                override fun onResponse(call: Call?, response: Response) {
                    if (response.isSuccessful) {
                        val string = response.body()!!.string()

                        Log.d("接口数据 ",string)
                        listener.OnRequestSuccess(string)
                    } else {
                        listener.OnRequestErro("${response.message()}")
                    }
                }
            })
            return call
        } catch (e: Exception) {

        }
        return null
    }

    /**
     * 上传文件
     */
    fun upLoadFile(url: String, file: File, hashMap: HashMap<String, String>, listener: RequestListener) {

        val type = MediaType.parse("application/octet-stream")
        val fileBody = RequestBody.create(type, file)


        val multipartBody = MultipartBody.Builder()
            .setType(MultipartBody.ALTERNATIVE)
        hashMap.forEach {
            multipartBody.addFormDataPart(it.key, it.value)
        }
        multipartBody.addFormDataPart("file", file.name, fileBody)
            .build()

        var request = Request.Builder().url(url)
            .addHeader("mac", SmdtManagerUtils.smdtGetEthMacAddress())
            .post(multipartBody.build()).build()

        request().newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                listener.OnRequestErro("${e.message}")
            }
            override fun onResponse(call: Call, response: Response) {
                if (response.isSuccessful) {
//                    var toJson = Gson().toJson(response.body())
                    listener.OnRequestSuccess(response.body()!!.string())
                } else {
                    listener.OnRequestErro("${response.message()}")
                }
            }

        })

    }

}